package cn.shanke.torrentmanagerserver.btclient;

import cn.shanke.torrentmanagerserver.btclient.model.TmSessionInfo;
import cn.shanke.torrentmanagerserver.btclient.model.TmTorrentInfo;
import cn.shanke.torrentmanagerserver.btclient.model.TmTorrentInfoSimple;
import cn.shanke.torrentmanagerserver.model.Client;
import com.google.common.collect.Lists;
import nl.stil4m.transmission.api.TransmissionRpcClient;
import nl.stil4m.transmission.api.domain.*;
import nl.stil4m.transmission.api.domain.ids.OmittedIds;
import nl.stil4m.transmission.api.domain.ids.ShaListIds;
import nl.stil4m.transmission.rpc.RpcException;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Base64;
import java.util.List;

public class TransmissionClient extends BtClient{

    public static final List<String> TORRENT_INFO_FIELDS_SIMPLE = Lists.newArrayList(
            "id", "name", "downloadDir", "hashString", "totalSize", "status", "addedDate", "trackers", "isPrivate", "magnetLink"
    );

    TransmissionRpcClient rpcClient;

    public static TransmissionClient init(TransmissionRpcClient rpcClient, Client config) {
        TransmissionClient client = new TransmissionClient();
        client.rpcClient = rpcClient;
        client.config = config;
        return client;
    }

    @Override
    public SessionStats getSessionStats() throws RpcException {
        return rpcClient.getSessionStats();
    }

    @Override
    public TmSessionInfo getSessionInfo() throws RpcException {
        SessionInfo info = rpcClient.getSessionInfo();
        return TmSessionInfo.wrapTransmission(info);
    }

    @Override
    public TmTorrentInfo addTorrent(String url, String metainfo, String downloadPath, boolean start) throws RpcException {
        AddTorrentInfo addTorrentInfo = new AddTorrentInfo();

        if (!StringUtils.hasText(metainfo)) {
            // metainfo，种子文件优先
            addTorrentInfo.setMetainfo(metainfo);
        } else {
            // 链接地址
            addTorrentInfo.setFilename(url);
        }

        if (!StringUtils.hasText(downloadPath)) {
            addTorrentInfo.setDownloadDir(downloadPath);
        }

        addTorrentInfo.setPaused(!start);

        AddedTorrentInfo result = rpcClient.addTorrent(addTorrentInfo);
        TorrentInfo info = result.getTorrentInfo();
        return TmTorrentInfo.wrapTransmission(info);
    }

    @Override
    public TmTorrentInfo addTorrent(String url, String downloadPath, boolean start) throws RpcException {
        return addTorrent(url, null, downloadPath, start);
    }

    @Override
    public TmTorrentInfo addTorrent(Path file, String downloadPath, boolean start) throws RpcException, IOException {
        String metainfo = Base64.getEncoder().encodeToString(Files.readAllBytes(file));
        return addTorrent(null, metainfo, downloadPath, start);
    }

    @Override
    public List<TmTorrentInfoSimple> getAllTorrentInfo() throws RpcException {
        TorrentInfoCollection result = rpcClient.getTorrentInfo(new TorrentGetRequestInfo(new OmittedIds(), TORRENT_INFO_FIELDS_SIMPLE));
        List<TorrentInfo> torrentInfos =  result.getTorrents();
        return TmTorrentInfoSimple.wrapTransmission(torrentInfos);
    }

    @Override
    public TmTorrentInfo getTorrentInfo(String id) throws RpcException {
        TorrentInfoCollection result = rpcClient.getTorrentInfo(new TorrentGetRequestInfo(new ShaListIds(id), Constants.TORRENT_INFO_FIELDS));
        TorrentInfo torrentInfo =  result.getTorrents().size()>0 ? result.getTorrents().get(0) : null;
        return TmTorrentInfo.wrapTransmission(torrentInfo);
    }

    @Override
    public TmTorrentInfoSimple getTorrentInfoSimple(String id) throws RpcException {
        TorrentInfoCollection result = rpcClient.getTorrentInfo(new TorrentGetRequestInfo(new ShaListIds(id), Constants.TORRENT_INFO_FIELDS));
        TorrentInfo torrentInfo =  result.getTorrents().size()>0 ? result.getTorrents().get(0) : null;
        return TmTorrentInfoSimple.wrapTransmission(torrentInfo);
    }

    @Override
    public List<TmTorrentInfo> getTorrentInfo(List<String> ids) throws RpcException {
        TorrentInfoCollection result = rpcClient.getTorrentInfo(new TorrentGetRequestInfo(new ShaListIds(ids), Constants.TORRENT_INFO_FIELDS));
        return TmTorrentInfo.wrapTransmission(result.getTorrents());
    }

    @Override
    public void setTorrentLocation(List<String> ids, String location, boolean move) throws RpcException {
        SetTorrentLocationInfo setTorrentLocationInfo = SetTorrentLocationInfo.builder()
                .ids(new ShaListIds(ids))
                .location(location)
                .move(move)
                .build();
        rpcClient.setTorrentLocation(setTorrentLocationInfo);
    }

    @Override
    public void verify(List<String> ids) throws RpcException {
        rpcClient.doAction(new ShaListIds(ids), TorrentAction.VERIFY);
    }

    @Override
    public void removeTorrent(List<String> ids, boolean delFile) throws RpcException {
        // delFile 删除本地文件无效
        rpcClient.removeTorrent(new RemoveTorrentInfo(new ShaListIds(ids), delFile));
    }

    @Override
    public void stop(List<String> ids) throws RpcException {
        rpcClient.doAction(new ShaListIds(ids), TorrentAction.STOP);
    }

    @Override
    public void start(List<String> ids) throws RpcException {
        rpcClient.doAction(new ShaListIds(ids), TorrentAction.START);
    }
}
